package com.wondertek.poms.pre.controller;

import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONUtil;
import com.wondertek.poms.common.constant.Constants;
import com.wondertek.poms.common.utils.validate.ValidateFilter;
import com.wondertek.poms.pre.manager.filter.MainProcessPreFilter;
import com.wondertek.poms.transform.xmlvo.SvcCont;
import com.wondertek.poms.transform.xmlvo.SyncRequest;
import com.wondertek.poms.transform.xmlvo.SyncResponse;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.w3c.dom.Document;

import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@RestController
@RequestMapping(value = "/poms-admin")
@Data
public class SyncController {
	@Autowired
	private MainProcessPreFilter mainProcessPreFilter;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
//    @Autowired
//    private JmsTemplate jmsTemplate;
//    @Resource(name = "contentQueue")
//    private Queue contentQueue;
    @Autowired
    private AmqpTemplate amqpTemplate;

    @Value(value="${syncpre.onoff:on}")
    public String onOff;
    @Value(value = "${syncpre.filter.switch}")
    public String filterSwitch;
    @Value(value="${syncpre.default.expire:3}")
    public Integer defaultExpire;

    @PostMapping(value = "/syncContentNotify", consumes = {
            MediaType.TEXT_XML_VALUE}, produces = MediaType.TEXT_XML_VALUE)
    @Transactional(readOnly = false)
    public SyncResponse sync(@RequestBody SyncRequest syncRequest) {
    	log.info("同步主流程|媒资同步进来的任务syncRequest={}", syncRequest.toString() + "|开关为：" + onOff);
    	if ("off".equals(onOff)) {
            return mainProcessPreFilter.backResponse(SyncResponse.back_error_500104, "主流程暂时关闭，请稍后在同步");
        }

    	SvcCont svcCont = syncRequest.getSvcCont();
    	String contentID = svcCont.getContentID();

        try {
			log.info("同步流程|内容ID:" + contentID + "|同步数据为:" + svcCont);
            // 1.insert redis remove repeat
            String md5Key = redisRepeat(contentID, svcCont);
            if (md5Key == null) {
            	return mainProcessPreFilter.backResponse(SyncResponse.back_error_500103, "有两条相同任务存在，请同步慢一点");
            }
            syncRequest.setMd5Key(md5Key);
            // 2.获取媒资id、过滤原图不存在
        	SyncResponse response = this.filter(syncRequest, svcCont);
			if (response != null) {
				return response;
			}

            // 3.insert mq
            sendMq(syncRequest);
        } catch (Exception e) {
            log.error("同步流程业务异常|内容ID:" + contentID, e);
            return mainProcessPreFilter.backResponse(SyncResponse.back_error_500101, "同步流程业务异常,请联系POMS业务负责人");
        }

    	return mainProcessPreFilter.backResponse(SyncResponse.back_success, SyncResponse.back_success);
    }

	/**
	 * <p><b>Title:</b> getAssetId</p>
	 * <p><b>Description:</b> </p>
	 * @author douzi
	 * @param syncRequest
	 * @param svcCont
	 */
	private SyncResponse filter(SyncRequest syncRequest, SvcCont svcCont) {
		List<String> messageList = ValidateFilter.getFilterMessage(svcCont, Constants.VALIDATE_DEFAULT);
        if (!messageList.isEmpty()) {
            return mainProcessPreFilter.backResponse(SyncResponse.back_request_error, messageList.toString());
        }
        //获取document对象
		Document document = mainProcessPreFilter.getDocument(svcCont);
		//1.上游数据校验
		if ("on".equals(filterSwitch)){
			SyncResponse response = mainProcessPreFilter.filterData(document,svcCont);
			if (response != null){
				return response;
			}
		}

		// 2.获取媒资id
        String assetId = mainProcessPreFilter.getXmlValueByKey(document , Constants.ASSET_ID);
        if (StrUtil.isBlank(assetId)) {
    		log.info("assetId is null:" + svcCont.getContentID());
        	return mainProcessPreFilter.backResponse(SyncResponse.back_error_500102, "Metadata_M.xml not exists");
        }
        syncRequest.setAssetId(assetId);
		if ("on".equals(filterSwitch)){
        //3.过滤原图不存在，或者大小为零
			SyncResponse resp = mainProcessPreFilter.filterSrcImages(svcCont);
			if (resp != null){
				return resp;
			}
		}
        return null;
	}


    /**
     * <p><b>Title:</b> redisNoRepeat </p>
     * <p><b>Description:</b> 放入redis队列 </p>
     *
     * @param id
     * @param svcCont
     * @return
     * @author douzi
     */
    private String redisRepeat(String id, SvcCont svcCont) {
    	int randomInt = RandomUtil.randomInt(200);
    	log.info("同步流程|内容ID:" + id + "|线程随机睡:" + randomInt);
		ThreadUtil.sleep(randomInt);
        String key = id + Constants.REDIS_KEY_SPLIT
                + svcCont.getOprCode()
                + Constants.REDIS_KEY_SPLIT
                + svcCont.getUpdateFields();
        String md5Key = SecureUtil.md5(key);
        String value = redisTemplate.opsForValue().get(md5Key);
        if (ObjectUtil.equal(value, Constants.YES_1)) {
            log.warn("同步流程|内容ID:" + id + "|md5Key:" + md5Key + "已存在");
            return null;
        }
        redisTemplate.opsForValue().set(md5Key, Constants.YES_1,
        		defaultExpire, TimeUnit.MINUTES);
        return md5Key;
    }

    /**
     * <p><b>Title:</b> sendMq </p>
     * <p><b>Description:</b> 同步内容放入mq </p>
     *
     * @param request
     * @author ma
     */
    private void sendMq(SyncRequest request) {
		String jsonStr = JSONUtil.toJsonStr(request);
		log.info("同步流程|发送队列消息开始======");
		amqpTemplate.convertAndSend(Constants.QUEUE_SYNC_CONTENT, jsonStr);
		log.info("同步流程|发送队列消息:" + jsonStr);
    }

    @GetMapping("/changeStatus")
    public String changeStatus(String status){
	    log.info("起始开关状态为"+this.filterSwitch);
	    this.filterSwitch=status;
	    log.info("当前的开关状态为"+this.filterSwitch);
	    return "修改成功";

    }
}
